<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
    .box {
        width: 100px;
        height: 100px;
        background-color: red;
    }

    .enter-from {
        transform: translateX(200px);
    }

    .enter-to {
        transform: translateX(0);
    }

    .enter-active {
        transition: transform 1s ease-in-out;
    }


    /* 初始状态 */
    .leave-from {
        transform: translateX(0);
    }

    /* 结束状态 */
    .leave-to {
        transform: translateX(200px);
    }

    /* 过渡过程 */
    .leave-active {
        transition: transform 2s ease-out;
    }
</style>

<body>
</body>
<script>
    // 创建 class 为 box 的 DOM 元素
    const el = document.createElement('div')
    el.classList.add('box')

    // 在 DOM 元素被添加到页面之前，将初始状态和运动过程定义到元素上
    el.classList.add('enter-from') // 初始状态
    el.classList.add('enter-active') // 运动过程

    // 将元素添加到页面
    document.body.appendChild(el)

    // 嵌套调用 requestAnimationFrame
    requestAnimationFrame(() => {
        requestAnimationFrame(() => {
            el.classList.remove('enter-from')
            el.classList.add('enter-to')
            // 监听 transitionend 事件以结束动画
            el.addEventListener('transitionend', () => {
                el.classList.remove('enter-to')
                el.classList.remove('enter-active')
            })
        })
    })
    el.addEventListener('click', () => {
        // 定义卸载动作
        const performRemove = () => el.parentNode.removeChild(el)

        // 设置初始状态
        el.classList.add('leave-from')
        el.classList.add('leave-active')

        // 强制重绘
        document.body.offsetHeight

        // 在下一帧改变状态
        requestAnimationFrame(() => {
            requestAnimationFrame(() => {
                // 改变状态
                el.classList.remove('leave-from')
                el.classList.add('leave-to')

                // 在动画结束后，移除元素
                el.addEventListener('transitionend', () => {
                    el.classList.remove('leave-to')
                    el.classList.remove('leave-active')
                    performRemove()
                })
            })
        })
    })

</script>

</html>